using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using Intuipic.Data;

namespace Intuipic.Navigation
{ 
	public partial class Panel
	{
		public static readonly DependencyProperty IsImageCyclingEnabledProperty = DependencyProperty.Register("IsImageCyclingEnabled",
			typeof(bool),
			typeof(Panel),
			new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

		public static readonly DependencyProperty IsCurrentFileMarkedForDeletionProperty = DependencyProperty.Register("IsCurrentFileMarkedForDeletion",
			typeof(bool),
			typeof(Panel));

		public static readonly DependencyProperty IsFolderSelectionOpenProperty = DependencyProperty.Register("IsFolderSelectionOpen",
			typeof(bool),
			typeof(Panel));

		public static readonly RoutedEvent SourceDirectoriesChangedEvent = EventManager.RegisterRoutedEvent("SourceDirectoriesChanged",
			RoutingStrategy.Bubble,
			typeof(RoutedEventHandler),
			typeof(Panel));

		public DesktopInformation[] DesktopInformation
		{
			get
			{
				//array so the ItemsSource can bind to it, no other reason
				return new DesktopInformation[] { Data.DesktopInformation.Instance};
			}
		}

		public Timer Timer
		{
			get
			{
				return _timer;
			}
		}

		public bool IsImageCyclingEnabled
		{
			get
			{
				return (bool) GetValue(IsImageCyclingEnabledProperty);
			}
			set
			{
				SetValue(IsImageCyclingEnabledProperty, value);
			}
		}

		public bool IsCurrentFileMarkedForDeletion
		{
			get
			{
				return (bool) GetValue(IsCurrentFileMarkedForDeletionProperty);
			}
			set
			{
				SetValue(IsCurrentFileMarkedForDeletionProperty, value);
			}
		}

		public bool IsFolderSelectionOpen
		{
			get
			{
				return (bool) GetValue(IsFolderSelectionOpenProperty);
			}
			set
			{
				SetValue(IsFolderSelectionOpenProperty, value);
			}
		}

		public Settings Settings
		{
			get
			{
				return Settings.Current;
			}
		}

		public double SmallChange
		{
			get
			{
				return _delaySlider.SmallChange;
			}
		}

		public double MaximumChange
		{
			get
			{
				return _delaySlider.Maximum;
			}
		}

		public double MinimumChange
		{
			get
			{
				return _delaySlider.Minimum;
			}
		}

		public event RoutedEventHandler SourceDirectoriesChanged
		{
			add
			{
				AddHandler(SourceDirectoriesChangedEvent, value);
			}
			remove
			{
				RemoveHandler(SourceDirectoriesChangedEvent, value);
			}
		}

		public Panel()
		{
			ResourceDictionary images = new ResourceDictionary();
			images.Source = new Uri("pack://application:,,,/Navigation/Images.xaml");
			Resources.MergedDictionaries.Add(images);
			Resources["SliderGradientConverter"] = new SliderGradientConverter(this);
			Resources["TreeItemImageConverter"] = new TreeItemImageConverter();
			Resources["TreeViewItemTemplateSelector"] = new TreeViewItemTemplateSelector(this);
			Resources["FolderItemContainerStyleSelector"] = new FolderItemContainerStyleSelector(this);
			InitializeComponent();
		}

		private void Next(object sender, RoutedEventArgs e)
		{
			Commands.Next.Execute(null, this);
		}

		private bool _settingsChanged;

		private void _foldersPopup_Opened(object sender, EventArgs e)
		{
			_settingsChanged = false;
			Settings.SourceDirectories.CollectionChanged += SourceDirectories_CollectionChanged;
		}

		private void _foldersPopup_Closed(object sender, EventArgs e)
		{
			Settings.SourceDirectories.CollectionChanged -= SourceDirectories_CollectionChanged;

			if (_settingsChanged)
			{
				RaiseEvent(new RoutedEventArgs(SourceDirectoriesChangedEvent));
			}
		}

		private void SourceDirectories_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
		{
			_settingsChanged = true;
		}

		private void _foldersPopup_KeyDown(object sender, KeyEventArgs e)
		{
			//don't let keypresses bubble out of the popup because it makes keyboard nav in the tree view impossible
			e.Handled = true;
		}

		private void _foldersPopup_MouseDown(object sender, MouseEventArgs e)
		{
			//don't let clicks bubble out of popup because then the popup will close
			e.Handled = true;
		}

		//determines where the slider gradients should be placed based on the current ratio of the cycle complete
		private sealed class SliderGradientConverter : IValueConverter
		{
			private readonly Panel _panel;
			private Track _track;

			public SliderGradientConverter(Panel navigation)
			{
				_panel = navigation;
			}

			public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
			{
				if (_track == null)
				{
					_track = _panel._delaySlider.Template.FindName("PART_Track", _panel._delaySlider) as Track;
				}

                if (_track == null)
                {
                    return DependencyProperty.UnsetValue;
                }

				Debug.Assert(_track != null);
				double ratio = (double) value;
				//calculate the maximum allocatable based on the current position of the slider's track
				double maximum = Math.Max(0d, _panel._delaySlider.Value / _panel._delaySlider.Maximum - (_track.ActualWidth / _panel.ActualWidth));
				//now return a ratio of that maximum based on the elapsed time as specified by ratio
				return ratio * maximum;
			}

			public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
			{
				return DependencyProperty.UnsetValue;
			}
		}

		//converts between an IFileSystemInformation and an image source
		private sealed class TreeItemImageConverter : IMultiValueConverter
		{
			public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
			{
				InformationBase informationBase = values[0] as InformationBase;
				Debug.Assert(informationBase != null);
				bool isExpanded = (bool) values[1];

				return isExpanded ? informationBase.OpenIcon : informationBase.ClosedIcon;
			}

			public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
			{
				throw new NotSupportedException();
			}
		}

		private sealed class TreeViewItemTemplateSelector : DataTemplateSelector
		{
			private readonly Panel _panel;

			public TreeViewItemTemplateSelector(Panel navigation)
			{
				_panel = navigation;
			}

			public override DataTemplate SelectTemplate(object item, DependencyObject container)
			{
				if ((item is DriveInformation) || (item is DirectoryInformation))
				{
					return _panel.Resources["TreeViewItemWithCheckboxDataTemplate"] as DataTemplate;
				}
				else
				{
					return _panel.Resources["TreeViewItemWithoutCheckboxDataTemplate"] as DataTemplate;
				}
			}
		}

		private sealed class FolderItemContainerStyleSelector : StyleSelector
		{
			private readonly Panel _panel;

			public FolderItemContainerStyleSelector(Panel navigation)
			{
				_panel = navigation;
			}

			public override Style SelectStyle(object item, DependencyObject container)
			{
				if (item is DesktopInformation)
				{
					return _panel.Resources["DesktopInformationStyle"] as Style;
				}
				else if (item is MyComputerInformation)
				{
					return _panel.Resources["MyComputerInformationStyle"] as Style;
				}
				else if (item is DirectoryInformation)
				{
					return _panel.Resources["DirectoryInformationItemStyle"] as Style;
				}
				else
				{
					return null;
				}
			}
		}
	}
}